const axios = require('axios').default;
const MD5 = require('./md5');
const colors = require('colors');
const getProjectConfig = {
  langMap: {
    'en-US': 'en',
    en: 'en',
    'zh-TW': 'cht',
    'zh-HK': 'cht',
    'fr-FR': 'fra',
    'de-DE': 'de',
    'it-IT': 'it',
    'ja-JP': 'jp',
    'ko-KR': 'kor',
    'ru-RU': 'ru',
  },
};

const BAI_DU_LIMIT_WORD = 800;

function withTimeout(promise, ms) {
  const timeoutPromise = new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(`Promise timed out after ${ms} ms.`);
    }, ms);
  });
  return Promise.race([promise, timeoutPromise]);
}

function translateTextByBaidu(texts, baiduAppid, baiduKey, toLang) {
  const textsStr = texts.join('\n');
  const { langMap } = getProjectConfig;
  const salt = new Date().getTime();
  const signStr = baiduAppid + textsStr + salt + baiduKey;
  const sign = MD5(signStr);
  return withTimeout(
    new Promise((resolve, reject) => {
      axios
        .get('http://api.fanyi.baidu.com/api/trans/vip/translate', {
          params: {
            q: textsStr,
            from: 'auto',
            to: langMap[toLang] || '',
            appid: baiduAppid,
            salt,
            sign,
          },
        })
        .then(({ status, data }) => {
          if (status === 200) {
            if (data.error_code) {
              console.log(
                `${colors.red('➤ ERROR')} ${colors.red(data.error_msg)}`
              );
              reject(data);
              process.exit(0);
            } else {
              const { trans_result } = data;
              resolve(trans_result ? trans_result.map(({ dst }) => dst) : []);
            }
          } else {
            console.log(
              `${colors.red('➤ ERROR')} ${colors.red(data.error_msg)}`
            );
            reject(data);
            process.exit(0);
          }
        });
    }),
    5000
  );
}

function cutText(allTexts) {
  const len = allTexts.length;
  const textLength = allTexts.join('').length;
  if (textLength < BAI_DU_LIMIT_WORD - len) {
    return [allTexts];
  }

  const res = [];
  const count = Math.ceil(textLength / BAI_DU_LIMIT_WORD);
  const num = Math.floor(len / count);
  for (let i = 0; i <= count; i += 1) {
    res.push(allTexts.slice(num * i, num * (i + 1)));
  }

  return res;
}

async function translateTexts(texts, baiduAppid, baiduKey, toLang = 'en-US') {
  return new Promise(async (resolve, reject) => {
    const allTexts = texts.reduce((acc, curr) => {
      // 避免翻译的字符里包含数字或者特殊字符等情况
      const reg = /[^a-zA-Z\x00-\xff]+/g;
      const findText = curr.match(reg);
      const transText = findText ? curr : '中文符号';
      return acc.concat(transText);
    }, []);
    try {
      let result = [];
      for await (const piece of cutText(allTexts)) {
        if (piece.length && piece.join('').length) {
          const translated = await translateTextByBaidu(
            piece,
            baiduAppid,
            baiduKey,
            toLang
          );
          result = [...result, ...translated];
        }
      }
      // return [...result];
      resolve([...result]);
    } catch (err) {
      reject(err);
    }
  });
}

async function translateText(text, baiduAppid, baiduKey, toLang = 'en-US') {
  return new Promise(async (resolve, reject) => {
    // 避免翻译的字符里包含数字或者特殊字符等情况
    const reg = /[^a-zA-Z\x00-\xff]+/g;
    const findText = text.match(reg);
    text = findText ? text : '中文符号';
    try {
      if (text.length) {
        const translated = await translateTextByBaidu(
          [text],
          baiduAppid,
          baiduKey,
          toLang
        );
        resolve(translated[0]);
      }
    } catch (err) {
      reject(err);
    }
  });
}

async function translateFiles(files) {
  let translatedFiles = [];
  for await (let file of files) {
    const { filePath, texts: textObjs } = file;
    const texts = Array.from(new Set(textObjs.map((textObj) => textObj.text)));
    const translatedTexts = await translateTexts(texts);
    translatedFiles.push({ filePath, texts, translatedTexts });
  }
  return translatedFiles;
}
module.exports = {
  translateFiles,
  translateTexts,
  translateText,
};
